package com.atguigu.gulimall.ware.listener;

import com.atguigu.common.to.mq.OrderTo;
import com.atguigu.common.to.mq.StockLockedTo;
import com.atguigu.gulimall.ware.service.WareSkuService;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
/**
 * @创建人: 放生
 * @创建时间: 2022/5/6
 * @描述:
 */
@Service
@RabbitListener(queues = "stock.release.stock.queue")
public class StockReleaseListener {

    @Autowired
    WareSkuService wareSkuService;

    /**
     *当前的消费方法是，在库存服务发送到延迟队列的消费
     * 锁定成功，将锁定的详情发送MQ的延时队列（40分钟）中并且把具体的锁定信息以流水表的形式存入mysql，
     * MQ到时消费（到时后根据订单的状态来解锁库存，因为可能在ware服务锁定库存成功，
     * 但是在订单服务中后续操作出了异常，或者30分钟没有支付）总之根据订单的状态来消费数据，
     * 是解锁库存，还是反向补偿。
     */
    @RabbitHandler
    public void handleStockLockedRelease(StockLockedTo to, Message message, Channel channel) throws IOException {

        System.out.println("收到解锁库存的消息...");
        try{
            //当前消息是否被第二次及以后（重新）派发过来了。
//            Boolean redelivered = message.getMessageProperties().getRedelivered();
            wareSkuService.unlockStock(to);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        }catch (Exception e){
            channel.basicReject(message.getMessageProperties().getDeliveryTag(),true);
        }

    }

    /**
     *当前的消费方法是，订单服务在关单后发送过来的消费
     * 考虑到特殊的情况下，比如我解锁的队列时间是40分钟，订单的是30分钟，由于订单的服务机器卡顿，延时间等原因，
     * 订单服务延迟了11分钟后在发送数据到mq，那么自动关单就是在41分钟之后了，这个时候解锁的消费者已经消费完成了，
     * 所以后面的操作还需要在关单的时候再次发送数据到解锁队列
     */
    @RabbitHandler
    public void handleOrderCloseRelease(OrderTo orderTo, Message message, Channel channel) throws IOException {
        System.out.println("订单关闭准备解锁库存...");
        try{
            wareSkuService.unlockStock(orderTo);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        }catch (Exception e){
            channel.basicReject(message.getMessageProperties().getDeliveryTag(),true);
        }

    }

}
